/*
 * common.cpp
 *
 *  Created on: Jan 9, 2009
 *      Author: yospaly
 */

#define CINTERFACE

#include "common.h"
#include <wx/ffile.h>
#include <wx/log.h>

wxArrayString split_string_ws(const wxString& str) {
    wxArrayString list;

    int x = 0;
    int i = 0;

    do {
        if (str[i]==_T(' ') || str[i]==_T('\t')) {
            i++;
            continue;
        }

        for (x=i+1; x<str.Length(); x++) {
            if (str[x]==_T(' ') || str[x]==_T('\t')) {
                break;
            }
        }

        list.Add(str.Mid(i, x-i));
        i = x;
    } while ( i < str.Length() );

    return list;
}

wxString format_size(double s) {
	// B
	double d = s / 1024;
	if (d < 1.0) {
		return wxString::Format(_T("%d B"), s);
	}

	// KB
	double tmp = d;
	d = d / 1024;
	if (d < 1.0) {
		return wxString::Format(_T("%.1f KB"), tmp);
	}

	return wxString::Format(_T("%.1f MB"), d);
}

wxString format_size_str(const wxString& size) {
	long s = 0;

	if (!size.ToLong(&s)) {
		return _T("");
	}

	// B
	double d = (double) s / 1024;
	if (d < 1.0) {
		return size + _T(" B");
	}

	// KB
	double tmp = d;
	d = d / 1024;
	if (d < 1.0) {
		return wxString::Format(_T("%.1f KB"), tmp);
	}

	return wxString::Format(_T("%.1f MB"), d);
}

int version_compare(const wxString& a, const wxString& b) {
	if (a == b)
		return 0;

	size_t apos1, apos2 = 0, bpos1, bpos2 = 0;
	size_t alen = a.length(), blen = b.length();
	bool isnum;
	int cval;

	while (apos2 < alen && bpos2 < blen) {
		apos1 = apos2;
		bpos1 = bpos2;

		if (wxIsdigit(a[apos2])) {
			while (apos2 < alen && wxIsdigit(a[apos2]))
				apos2++;
			while (bpos2 < blen && wxIsdigit(b[bpos2]))
				bpos2++;
			isnum = true;
		} else {
			while (apos2 < alen && !wxIsdigit(a[apos2]))
				apos2++;
			while (bpos2 < blen && !wxIsdigit(b[bpos2]))
				bpos2++;
			isnum = false;
		}

		/* if (apos1 == apos2) { a logical impossibility has happened; } */

		/* isdigit(a[0]) != isdigit(b[0])
		 * arbitrarily sort the non-digit first */
		if (bpos1 == bpos2)
			return (isnum ? 1 : -1);

		if (isnum) {
			/* skip numeric leading zeros */
			while (apos1 < alen && a[apos1] == '0')
				apos1++;
			while (bpos1 < blen && b[bpos1] == '0')
				bpos1++;

			/* if one number has more digits, it is greater */
			if (apos2 - apos1 > bpos2 - bpos1)
				return 1;
			if (apos2 - apos1 < bpos2 - bpos1)
				return -1;
		}

		/* do an ordinary lexicographic string comparison */
		cval = a.compare(apos1, apos2 - apos1, b, bpos1, bpos2 - bpos1);
		if (cval)
			return (cval < 1 ? -1 : 1);
	}

	/* ran out of characters in one string, without finding a difference */

	/* maybe they were the same version, but with different leading zeros */
	if (apos2 == alen && bpos2 == blen)
		return 0;

	/* the version with a suffix remaining is greater */
	return (apos2 < alen ? 1 : -1);
}



// #define CINTERFACE
#include <shlobj.h>

/* This part of the code must be in C because the C++ interface to COM
 doesn't work. */

extern "C" void make_link_2(const wxChar* exepath, const wxChar* args, 
		const wxChar* icon, const wxChar* lname)
{
	IShellLink *sl;
	IPersistFile *pf;
	// WCHAR widepath[MAX_PATH];

	CoCreateInstance (&CLSID_ShellLink, NULL,
			CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID *) & sl);
	sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, (void **) &pf);

	sl->lpVtbl->SetPath (sl, exepath);
	sl->lpVtbl->SetArguments (sl, args);
	sl->lpVtbl->SetIconLocation (sl, icon, 0);

	// MultiByteToWideChar (CP_ACP, 0, lname, -1, widepath, MAX_PATH);
	pf->lpVtbl->Save (pf, lname, TRUE);

	pf->lpVtbl->Release (pf);
	sl->lpVtbl->Release (sl);
}


/* Predicate: file is not currently in existence.
 * A file race can occur otherwise.
 */
extern "C" int mkcygsymlink (const wxChar* from, const wxChar* to) {
	wxFFile ffrom(from, _T("w+b"));
	
	ffrom.Write(SYMLINK_COOKIE);
	ffrom.Write(to);
	ffrom.Write("\0", 1);
	
	::SetFileAttributes(from, FILE_ATTRIBUTE_SYSTEM);
	
	return 1;
}

